/*************************************************************************
    > File Name: 1.select.c
    > Author: Ykk
    > Mail: 3393579535@qq.com 
    > Created Time: 2023年05月25日 星期四 20时59分16秒
 ************************************************************************/

#include<stdio.h>
#include<sys/select.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/time.h>
#include"network_utils.h"

#define POST 8888
#define IP "192.168.152.129"

int main(int argc,char *argv[])
{
	//创建套接字,绑定
	int lfd = tcp4bind(POST,IP);
	//监听
	Listen(lfd,128);
	int maxfd = lfd;
	fd_set rset,oldset;
	FD_ZERO(&rset);
	FD_ZERO(&oldset);
	FD_SET(lfd,&oldset);
	while(1)
	{
		rset = oldset;//将oldset赋给要监听的集合rset
		int n = select(maxfd+1,&rset,NULL,NULL,NULL);
		if(n < 0)
		{
			perror("");
			break;
		}
		else if(n == 0)
		{
			continue;//如果没有变化，重新监听
		}
		else//监听到了文件描述符的变化
		{
			//lfd变化 代表有新的连接到来
			if(FD_ISSET(lfd,&rset))
			{
				struct sockaddr_in cliaddr;
				socklen_t len = sizeof(cliaddr);
				int cfd = Accept(lfd,(struct sockaddr *)&cliaddr,&len);
				char ip[16] = "";
				printf("new client %s port %d\n",inet_ntop(AF_INET,&cliaddr.sin_addr.s_addr,ip,16),
						                        ntohs(cliaddr.sin_port));
				//将cfd添加到oldset中以下次监听
				FD_SET(cfd,&oldset);
				//更新maxfd
				if(cfd > maxfd)
					maxfd = cfd;
				//如果只有lfd变化，重新监听
				if(--n == 0)
					continue;i
			}

			//cfd 遍历lfd之后的文件描述符是否在rset集合中,如果在则cfd变化
			for(int i = lfd + 1;i <= maxfd;i++)
			{
				//如果i文件描述符在rset中
				if(FD_ISSET(i,&rset))
				{
					char buf[1500] = "";
					int ret = Read(i,buf,sizeof(buf));
					if(ret < 0)//出错,将cfd关闭，从oldset中删除cfd
					{
						perror("");
						close(i);
						FD_CLR(i,&oldset);
						continue;
					}
					else if(ret == 0)
					{
						printf("client close...\n");
						close(i);
						FD_CLR(i,&oldset);
					}
					else
					{
						printf("%s\n",buf);
						Write(i,buf,ret);
					}
				}
			}
		}
	}
	return 0;
}
